#include <sekai/VoiceDefESPEAK.h>
#include <sekai/VoiceSampler.h>
#include <sndfile.h>

SNDFILE *sf_debug;

float interp_linear(float *x, float *y, int nx, float ref) {
  int i;
  for (i = 0; i < nx - 1; i++) {
    if (ref >= x[i] && ref <= x[i + 1]) {
      float x1 = x[i];
      float x2 = x[i + 1];
      float tmp = (ref - x1) / (x2 - x1);
      return y[i] * (1 - tmp) + y[i + 1] * tmp;
    }
  }
  fprintf(stderr, "INTERP_LINEAR: out of range\n");
  return NAN;
}

class TestSynth : public VoiceSampler {
 public:
  TestSynth() : VoiceSampler(8192) {
    vox[0] = new VoiceDefESPEAK(
        "do.voicedef");
    vox[1] = new VoiceDefESPEAK(
        "re.voicedef");
    vox[2] = new VoiceDefESPEAK(
        "mi.voicedef");
    _impulseResponse = new float[1024];
  }

 protected:
  virtual bool addOnePulse() {
    int samplerate = 22050;
    float currentTime = inputPositionSamples() / samplerate;
    int index = (int)currentTime;
    if (index == 3) return false;
    // get impulse response

    float otoTime = currentTime;
    while (otoTime > 1.0) otoTime -= 1.0;

    if (index == 0) {
      float x[3] = {0, 0.10, 1.0};
      float y[3] = {0, 0.10, 0.20};
      otoTime = interp_linear(x, y, 3, otoTime);
    }
    if (index == 1) {
      float x[3] = {0, 0.10, 1.0};
      float y[3] = {0, 0.10, 0.20};
      otoTime = interp_linear(x, y, 3, otoTime);
    }
    if (index == 2) {
      float x[3] = {0, 0.20, 1.0};
      float y[3] = {0, 0.20, 0.40};
      otoTime = interp_linear(x, y, 3, otoTime);
    }

    int impulseResponseLength = 0;
    vox[index]->getImpulseResponse(otoTime, _impulseResponse,
                                   &impulseResponseLength,0);

    float f0[3] = {261.63, 293.67, 329.63};
    float output_f0 = f0[index];
    float period = samplerate * 1.0f / output_f0;

    VoiceSampler::hanningWindow(_impulseResponse, impulseResponseLength);
    // printf("index %i %i\n",index,impulseResponseLength);
    sf_write_float(sf_debug, _impulseResponse, impulseResponseLength);
    float mark = 1;
    sf_write_float(sf_debug, &mark, 1);
    ola(_impulseResponse, impulseResponseLength, period);

    return true;
  }

 private:
  VoiceDefESPEAK *vox[3];
  float *_impulseResponse;
};

int main() {
  TestSynth *synth = new TestSynth();

  SF_INFO info = {0};
  info.samplerate = 22050;
  info.channels = 1;
  info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
  SNDFILE *sf = sf_open("/tmp/test_espeak.wav", SFM_WRITE, &info);
  info.samplerate = 22050;
  info.channels = 1;
  info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
  sf_debug = sf_open("/tmp/test_espeak_debug.wav", SFM_WRITE, &info);

  while (1) {
    const int size = 1024;
    int fill = size * 4;

    float buffer_out[size];
    if (synth->readData(buffer_out, size, fill) == false) break;
    sf_write_float(sf, buffer_out, size);
  }

  sf_close(sf);
  sf_close(sf_debug);
}
